package pep

import (
	"fmt"
	"gitee.com/wtiany365/pep/wrapper"
	"github.com/facebookgo/inject"
	"github.com/micro/go-grpc"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/server"
	"sync"
)

type Controllers interface {
	Register(server.Server)
}
type Wrapper interface {
	Handler(fn server.HandlerFunc) server.HandlerFunc
}
type app struct {
	*DB          `inject:""`
	*Config      `inject:""`
	controllers  Controllers
	service_name string
	Wrapper      Wrapper
}

var a *app
var once sync.Once

func Get() *app {
	once.Do(func() {
		a = &app{}
	})
	return a
}
func (a *app) Run(consul_url, config_path, service_name string, controllers Controllers) (err error) {
	a.controllers = controllers
	a.service_name = service_name
	cfg, err := newConfig(consul_url, config_path)
	if err != nil {
		return
	}
	db, err := newDb(cfg.dbConfig)
	if err != nil {
		return
	}
	var g inject.Graph
	err = g.Provide(
		&inject.Object{Value: cfg},
		&inject.Object{Value: db},
		&inject.Object{Value: a},
		&inject.Object{Value: a.controllers},
	)
	if err != nil {
		return
	}
	err = g.Populate()
	if err != nil {
		return
	}
	a.initWrapper()
	return a.bootMicro()
}
func (a *app) initWrapper() {
	if a.Wrapper == nil {
		traceWrapper := &wrapper.Trace{}
		traceWrapper.Init(a.service_name, a.Config.zipkin.Url)
		a.Wrapper = traceWrapper
	}
}
func (a *app) bootMicro() (err error) {
	service := grpc.NewService(
		micro.Name(a.service_name),
		micro.WrapHandler(a.Wrapper.Handler),
	)
	service.Init()
	a.controllers.Register(service.Server())
	// Run server
	return service.Run()
}
